#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <math.h>

#define INT32 int
#define TRACEROUTE_RESULT_FILE "./result_traceroute.txt"

#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif

typedef struct _traceroute_result{
	char host[64];
	char host_addr[64];
	char err_code[64];
	char rt_times[64];
}TRACEROUTE_RESULT_T;

typedef struct _traceroute{
	char state[64];
	int res_time;
	int hop_num;
	int old_hop_num;
	TRACEROUTE_RESULT_T *hops;
}TRACEROUTE_T;

static TRACEROUTE_T traceroute={"None", 0, 0, 0, NULL};

void traceroute_start()
{
	char cmd[128] = {0};

	sprintf(cmd, "traceroute -w 2 -m 6 www.sohu.com 38 > %s", TRACEROUTE_RESULT_FILE);
	system(cmd);
}

void traceroute_diagnostic_init(int number)
{
	if(traceroute.hops){
		free(traceroute.hops);
		traceroute.hops = NULL;
	}

	traceroute.old_hop_num = traceroute.hop_num;
	traceroute.hop_num = number;
	traceroute.hops = (TRACEROUTE_RESULT_T *)malloc(sizeof(TRACEROUTE_RESULT_T)*number);
}

INT32 traceroute_get_hops_number(char *file)
{
	FILE *fp = NULL;
	char buff[512] = {0};
	char index[64] = {0};
	char host[64] = {0};
	char addr[64] = {0};
	char rta[32] = {0};
	char rtb[32] = {0};
	char rtc[32] = {0};
	int read_num = 0;
	int hops_number = 0;

	fp = fopen(file, "r");
	if(fp == NULL)
		return hops_number;

	while(fgets(buff, sizeof(buff), fp)){
		read_num =  sscanf(buff, " %[0-9] %[0-9,.] (%[^)])  %s ms  %s ms  %s ms*", index, host, addr, rta, rtb, rtc);
		if(read_num > 0){
			hops_number++;
		}
	}
	fclose(fp);
	
	return hops_number;
}

INT32 traceroute_diagnostic_load_result(char *file)
{
	FILE *fp = NULL;
	char buff[512] = {0};
	char index[64] = {0};
	char host[64] = {0};
	char addr[64] = {0};
	char rta[32] = {0};
	char rtb[32] = {0};
	char rtc[32] = {0};
	int irta;
	int irtb;
	int irtc;
	char rt_times[64] = {0};
	int read_num = 0;
	int hop_idx = 0;
	int res_time = 0;

	fp = fopen(file, "r");
	if(fp == NULL)
		return -1;

	printf("<----- file = [%s] ----->\n", file);
	while(fgets(buff, sizeof(buff), fp)){
		//printf("--------------------- buff=[%s]\n", buff);
		memset(index, 0, sizeof(index));
		memset(host, 0, sizeof(host));
		memset(addr, 0, sizeof(addr));
		memset(rta, 0, sizeof(rta));
		memset(rtb, 0, sizeof(rtb));
		memset(rtc, 0, sizeof(rtc));
		irta = 1;
		irtb = 1;
		irtc = 1;
		//read_num =  sscanf(buff, " %[0-9] %[0-9,.] (%[^)])  %s ms  %s ms  %s ms*", index, host, addr, rta, rtb, rtc);
		read_num =  sscanf(buff, " %[0-9] %[0-9,.] (%[^)])  %s ms  %s ms  %s ms*", index, host, addr, rta, rtb, rtc);
		printf("read_num = [%d]\n", read_num);
		if(read_num > 3){
			printf("dbg---> index=[%s, host=[%s]], addr=[%s,] rta=[%s], rtb=[%s], rtc=[%s]\n", index, host, addr, rta, rtb, rtc);
			irta = (int)round(atof(rta));
			irta = irta < 1 ? 1:irta;
			irtb = (int)round(atof(rtb));
			irtb = irtb < 1 ? 1:irtb;
			irtc = (int)round(atof(rtc));
			irtc = irtc < 1 ? 1:irtc;
			res_time = res_time + irta + irtb + irtc;
			//printf("dbg---> a irta=[%d], irtb=[%d], irtc=[%d]\n", irta, irtb, irtc);
			if(4 == read_num)
				sprintf(rt_times, "%d", irta);
			if(5 == read_num)
				sprintf(rt_times, "%d,%d", irta, irtb);
			if(6 == read_num)
				sprintf(rt_times, "%d,%d,%d", irta, irtb, irtc);

			strcpy(traceroute.hops[hop_idx].host, host);
			strcpy(traceroute.hops[hop_idx].host_addr, addr);
			strcpy(traceroute.hops[hop_idx].err_code, "255");
			strcpy(traceroute.hops[hop_idx].rt_times, rt_times);
			hop_idx++;
			//printf("rt_times=[%s]\n", rt_times);
		}
		else if(read_num > 0) // hop result are all *
		{
			printf("dbg---> index=[%s]\n", index);
			strcpy(traceroute.hops[hop_idx].host, host);
			strcpy(traceroute.hops[hop_idx].host_addr, "");
			strcpy(traceroute.hops[hop_idx].err_code, "255");
			strcpy(traceroute.hops[hop_idx].rt_times, "");
			hop_idx++;	
		}
	}

	traceroute.res_time = res_time;
	fclose(fp);

	printf("dbg---> return\n");	
	return 0;
}

void traceroute_diagnostic_update_data_model()
{
#if 0
	if(traceroute.old_hop_num != traceroute.hop_num){
		if(traceroute.old_hop_num > 0)
			tr69c_delObjInstance("Device.IP.Diagnostics.TraceRoute.RouteHops.", 1, traceroute.old_hop_num);
		tr69c_addObjInstance("Device.IP.Diagnostics.TraceRoute.RouteHops.", traceroute.hop_num);
	}
#endif
}

void traceroute_diagnostic_completed()
{
	strcpy(traceroute.state, "Completed");
	//addInformEventToList(INFORM_EVENT_DIAGNOSTICS_COMPLETE);
	//sendInform(NULL);
}

void traceroute_diagnostic_finished()
{
	int hop_number = 0;

	hop_number = traceroute_get_hops_number(TRACEROUTE_RESULT_FILE);
	traceroute_diagnostic_init(hop_number);
	traceroute_diagnostic_load_result(TRACEROUTE_RESULT_FILE);	
	//traceroute_diagnostic_update_data_model();
	traceroute_diagnostic_completed();
}

void traceroute_print()
{
	int idx = 0;

	printf("traceroute.state=[%s]\n", traceroute.state);
	printf("traceroute.res_time=[%d]\n", traceroute.res_time);
	printf("traceroute.hop_num=[%d]\n", traceroute.hop_num);
	for(idx = 0; idx < traceroute.hop_num; idx++){
		printf("traceroute.[%d] host=[%s] addr=[%s] err_code=[%s], rt_times=[%s]\n", idx,
			traceroute.hops[idx].host,
			traceroute.hops[idx].host_addr,
			traceroute.hops[idx].err_code,
			traceroute.hops[idx].rt_times);
	}
}

int main(int argc, char *argv[])
{
	int index;

	//traceroute_start();
	traceroute_diagnostic_finished();
	traceroute_print();

	return 0;
}
